package main

import (
	"encoding/json"
	"fmt"
	"nat_detect"
	"net"
	"os"
)

var otherServerAddr = "39.105.141.60:9900"

func CallServer2(pkt nat_detect.RawPkt) error {
	data, _ := json.Marshal(pkt)
	conn, err := net.Dial("tcp", otherServerAddr)
	if err != nil {
		return err
	}
	_, err = conn.Write(data)
	if err != nil {
		return err
	}
	conn.Close()
	return nil
}
func handleTest1(pkt nat_detect.RawPkt, conn *net.UDPConn, remoteAddr *net.UDPAddr) {
	echoPkt := nat_detect.RawPkt{
		Cmd:    "test1-echo",
		Id:     pkt.Id,
		Remote: remoteAddr.String(),
	}
	echo, _ := json.Marshal(echoPkt)
	fmt.Println("echo to ", echoPkt.String())
	_, err := conn.WriteToUDP(echo, remoteAddr)
	if err != nil {
		fmt.Println(err)
		return
	}
}

func handleTest2(pkt nat_detect.RawPkt, remoteAddr *net.UDPAddr) {
	echoPkt := nat_detect.RawPkt{
		Cmd:    "test2-echo",
		Id:     pkt.Id,
		Remote: remoteAddr.String(),
	}

	CallServer2(echoPkt)
}

func handleTest3(pkt nat_detect.RawPkt, remoteAddr *net.UDPAddr) {
	fmt.Println("handleTest3 dail ", remoteAddr.String())
	echoPkt := nat_detect.RawPkt{
		Cmd:    "test3-echo",
		Id:     pkt.Id,
		Remote: remoteAddr.String(),
	}
	echo, _ := json.Marshal(echoPkt)

	udpAddr, _ := net.ResolveUDPAddr("udp4", remoteAddr.String())
	udpConn, err := net.DialUDP("udp", nil, udpAddr)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("handleTest3 udp dial ok ")
	n, err2 := udpConn.Write(echo)
	if err2 != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("handleTest3 write ", n, " to client")
}

func handlePkt(pkt nat_detect.RawPkt, remoteAddr *net.UDPAddr, conn *net.UDPConn) {
	switch pkt.Cmd {
	case "test1":
		fmt.Println("cmd test1")
		handleTest1(pkt, conn, remoteAddr)
	case "test2":
		handleTest2(pkt, remoteAddr)
	case "test3":
		handleTest3(pkt, remoteAddr)
	}
}

func main() {
	const port = 9999

	if len(os.Args) > 1 {
		otherServerAddr = os.Args[1]
	}
	fmt.Println("another server is ", otherServerAddr)

	conn, err := net.ListenUDP("udp", &net.UDPAddr{
		IP:   net.ParseIP("0.0.0.0"),
		Port: port,
	})
	if err != nil {
		panic(err)
	}
	defer conn.Close()
	fmt.Printf("listent to %d \n", port)

	buf := make([]byte, 512) //一般认为udp包不要超过512 bytes
	for {
		rlen, remoteAddr, err := conn.ReadFromUDP(buf)
		if err != nil {
			fmt.Println("conn.ReadFromUDP error", err)
			continue
		}
		p := nat_detect.RawPkt{}
		json.Unmarshal(buf[:rlen], &p)
		go handlePkt(p, remoteAddr, conn)

	}
}
